#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include<stdbool.h>
#define WUP 100
#define WD 0
#define XUP 100
#define XD 0
#define CUP 100
#define CD 0  //各科成绩的上限和下限

typedef struct Node 
{
    unsigned long long id;//学号
    char name[50];//姓名
    char sex[10];//性别
    int wjf;//微积分成绩
    int xd;//线代成绩
    int cs;//程算成绩
    int sum;//总分
    struct Node* next;//指向下一个节点的指针

}node;

node list;//链表



//主菜单界面     0
void welcome();
//查询信息       1
void searchinf(node* plist);
//查找所有       1.1
node* searchall(node* plist);
//按学号查找     1.2
node* searchbyId(unsigned long long id, node* plist);
//按姓名查找     1.3
node* searchbyName(char name[50], node* plist);
//修改信息       2
void printFixStuInfo(node* list);
//增加信息       3
void addinf();
//读取文件方式增加数据      3.1
int readfile(node* plist);
//输入数据方式增加          3.2
void enterdata(node* plist);
//检查学号是否重复          3.2.1
int searchrepitition(unsigned long long newid, node* plist);
//检查数据是否有效          3.2.2
int searchwjf(int newgrade);
int searchxd(int newgrade);
int searchcs(int newgrade);
//删除信息       4
void deleteinf(node* pr);
//删除信息界面
void printDeleteStuInfo(node* plist);
//退出界面       5
void byebye();
//比较规则
bool cmp(node* plist ,int way);
//成绩排序
void StuScoreSort(node* plist,int way);
//保存文件
int savefile(node* plist);




int main()
{
    int choice, goon = 1;
    readfile(&list);
    while (goon)
    {
        system("cls");
        welcome();

        printf("        请输入对应数字进行操作:");

        if ((scanf("%d", &choice)) == 1)  // 如果读取成功则开始操作
        {
            switch (choice)
            {
            case 1:  searchinf(&list);
                printf("返回主菜单--1/退出程序--0:");
                scanf("%d", &goon);
                break;
            case 2:  printFixStuInfo(&list);
                printf("返回主菜单--1/退出程序--0:");
                scanf("%d", &goon);
                break;
            case 3:  addinf();
                printf("返回主菜单--1/退出程序--0:");
                scanf("%d", &goon);
                break;
            case 4:  printDeleteStuInfo(&list);
                printf("返回主菜单--1/退出程序--0:");
                scanf("%d", &goon);
                break;
            case 5:  byebye();
                goon = 0;
                break;
            default:  printf("读取失败┭┮ _ ┭┮请输入1~5的整数\n");
                printf("（按回车以继续）");

                getchar();//等待击键以继续
            }

        }
        else {
            printf("读取失败┭┮ _ ┭┮请输入1~5的整数\n");
            printf("（按回车以继续）");
        }
        getchar();//等待击键以继续
    }
    //如果读取失败则提示重新输入
    return 0;

}



void welcome()
{

    printf("----------------------------------------\n");
    printf("*          学生成绩管理系统            *\n");
    printf("*                                      *\n");
    printf("*            查询信息   1              *\n");
    printf("*            修改信息   2              *\n");
    printf("*            增加信息   3              *\n");
    printf("*            删除信息   4              *\n");
    printf("*            退出程序   5              *\n");
    printf("*                                      *\n");
    printf("----------------------------------------\n");

}
void searchinf(node* plist)
{
    system("cls");
    int choice = 0;
    int  way;
    char sname[50];
    unsigned long long sid;
    node* st;
    printf("查询所有------1\n");
    printf("按学号查询------2\n");
    printf("按姓名查询------3\n");
    printf("请输入查询方式：");
    scanf("%d", &choice);

    if (choice == 1)
    {
        searchall(&list);
        printf("\n总成绩倒序显示:1\n微积分成绩倒序显示:2\n线代成绩倒序显示:3\n程算成绩倒序显示:4\n继续:0\n请输入对应数字:");
        scanf("%d", &way);
        if (way == 1 || way == 2 || way == 3 || way == 4)
        {
            StuScoreSort(&list, way);
            searchall(&list);
        }
        else;
    }
    if (choice == 2)
    {
        printf("请输入要查询的学号:\n");
        scanf("%llu", &sid);
        st = searchbyId(sid, &list);
        if (st == NULL) {
            printf("查无此人\n");
        }
        else {
            st = st->next;
            printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
            printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", st->id, st->name, st->sex, st->wjf, st->xd, st->cs, st->sum);
        }
    }
    if (choice == 3) {
        printf("请输入要查询的姓名:\n");
        scanf("%s", &sname);
        st = searchbyName(sname, &list);
        if (st == NULL) {
            printf("查无此人\n");
        }
        else {
            st = st->next;
            printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
            printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", st->id, st->name, st->sex, st->wjf, st->xd, st->cs, st->sum);
        }
    }

}

node* searchall(node* plist)
{
    system("cls");
    printf("                         查询信息\n");
    printf("现有全部数据如下\n");
    printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
    node* p = plist->next;//用于遍历目前所有数据的指针
    for (; p; p = p->next)
        printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", p->id, p->name, p->sex, p->wjf, p->xd, p->cs, p->sum);//测试用测试用测
}
node* searchbyId(unsigned long long id, node* plist) {
    node* p = plist;
    while (p->next != NULL) 
    {
        if (p->next->id == id) 
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}
node* searchbyName(char name[50], node* plist) 
{
    node* p = plist;
    while (p->next != NULL) 
    {
        if (strcmp(name,p->next->name) == 0)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}


void printFixStuInfo()
{
    refix:;
    system("cls");
    int choice = 0;
    printf("按学号修改------1\n");
    printf("按姓名修改------2\n");
    printf("请输入修改方式：");
    scanf("%d", &choice);
    if (choice == 1)
    {
        system("cls");
        unsigned long long id;
        int choice = -1;
        printf("请输入要查找的学生学号：");
        scanf("%llu", &id);
        node* st = searchbyId(id, &list);
        if (st == NULL)
        {
            printf("查无此人！\n");

        }
        else
        {
            st = st->next;



            while (1)
            {
                system("cls");
                printf("该学生现有信息如下：\n");
                printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
                printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", st->id, st->name, st->sex, st->wjf, st->xd, st->cs, st->sum);
                printf("修改姓名------1\n");
                printf("修改性别------2\n");
                printf("修改微积分--------3\n");
                printf("修改线性代数--------4\n");
                printf("修改程算--------5\n");
                printf("请输入要修改的信息：");

                scanf("%d", &choice);
                switch (choice) {
                case 1:
                    printf("请输入姓名：");
                    scanf("%s", st->name);//标记11
                    break;
                case 2:
                    printf("请输入性别：");
                    scanf("%s", st->sex);//标记11
                    break;
                case 3:
                    printf("请输入微积分成绩：");
                    scanf("%d", &st->wjf);
                    break;
                case 4:
                    printf("请输入线性代数成绩：");
                    scanf("%d", &st->xd);
                    break;
                case 5:
                    printf("请输入程算成绩：");
                    scanf("%d", &st->cs);
                    break;
                }
                st->sum = st->wjf + st->xd + st->cs;
                printf("是否继续修改该学生信息？（是--1 / 否--0)：");
                scanf("%d", &choice);
                if (choice == 0)
                {
                    break;
                }

            }

            savefile(&list);
        }
    }
    else if (choice == 2)
    {
        system("cls");
        char name[50];
        int choice = -1;
        printf("请输入要查找的学生姓名：");
        scanf("%s", &name);
        node* st = searchbyName(name, &list);
        if (st == NULL)
        {
            printf("查无此人！\n");

        }
        else
        {
            st = st->next;


            while (1)
            {
                system("cls");
                printf("该学生现有信息如下：\n");
                printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
                printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", st->id, st->name, st->sex, st->wjf, st->xd, st->cs, st->sum);
                printf("修改学号------1\n");
                printf("修改性别------2\n");
                printf("修改微积分--------3\n");
                printf("修改线性代数--------4\n");
                printf("修改程算--------5\n");
                printf("请输入要修改的信息：");

                scanf("%d", &choice);
                switch (choice)
                {
                case 1:
                    printf("请输入学号：");
                    scanf("%llu", st->id);//标记11
                    break;
                case 2:
                    printf("请输入性别：");
                    scanf("%s", st->sex);//标记11
                    break;
                case 3:
                    printf("请输入微积分成绩：");
                    scanf("%d", &st->wjf);
                    break;
                case 4:
                    printf("请输入线性代数成绩：");
                    scanf("%d", &st->xd);
                    break;
                case 5:
                    printf("请输入程算成绩：");
                    scanf("%d", &st->cs);
                    break;
                }
                st->sum = st->wjf + st->xd + st->cs;
                printf("是否继续修改该学生信息？（是--1 / 否--0)：");
                scanf("%d", &choice);
                if (choice == 0)
                {
                    break;
                }

            }

            savefile(&list);
        }
    }
}


void addinf()

{
    system("cls");
    int addway;
    printf("                增加信息\n");
    printf("请选择添加方式(读取已有文件--1   输入数据--2):");
    reread:;//标签，用于当输入不符时重新读取输入
    scanf("%d", &addway);
    switch (addway)
    {
    case 1:readfile(&list); break;
    case 2:enterdata(&list); break;
    default:printf("请输入指定数字："); goto reread;//传送门
    }
    savefile(&list);

}
void byebye()


{
    printf("                退出界面");

}
int readfile(node* plist)
{
    FILE* fpr = fopen("C:\\Users\\weasley\\Desktop\\Project1\\original.txt", "r");
    node st;//临时储存读取的数据
    node* s = NULL;//开辟内存并链接储存数据
    node* t = plist;//尾指针

    if (fpr == NULL)
    {
        printf("文件读取失败");
    }
    else
    {
        while (fscanf(fpr, "%llu %s %s %d %d %d %d", &st.id, &st.name, &st.sex, &st.wjf, &st.xd, &st.cs, &st.sum) != EOF)
        {
           //printf("%llu %s %s %d %d %d %d\n", st.id, st.name, st.sex, st.wjf, st.xd, st.cs, st.sum);//测试用测试用测试用测试用测试用测试用
            s = (node*)malloc(sizeof(node));//开辟内存
            *s = st;
            t->next = s;
            t = s;
            t->next = NULL;


        }
    }
    return 0;
}
void enterdata(node* plist)
{
    int goon = 1;//用于判断是否继续
    node st;
    node* s = NULL;//开辟内存并链接储存数据
    while (goon)
    {
        int a;//用于判断是否需要重新输入
    reenter1:;
        system("cls");
        printf("请输入学号：");
        scanf("%llu", &st.id);
        a = searchrepitition(st.id, &list);
        if (a);//未找到重复则继续输入
        else
        {
            printf("该学号已存在，请重新输入(按回车键以继续)");
            getchar();
            getchar();//第一个getchar会读取缓冲区剩下的\n 不起作用
            goto reenter1;
        }
        printf("请输入姓名：");
        scanf("%s", &st.name);
        printf("请输入性别：");
        scanf("%s", &st.sex);
    reenter2:;
        printf("请输入微积分成绩：");
        scanf("%d", &st.wjf);
        a = searchwjf(st.wjf);
        if (a);
        else
        {
            printf("成绩应大于%d小于%d请重新输入", WD, WUP);
            getchar();
            getchar();//第一个getchar会读取缓冲区剩下的\n 不起作用
            goto reenter2;
        }
    reenter3:;
        printf("请输入线代成绩：");
        scanf("%d", &st.xd);
        a = searchwjf(st.xd);
        if (a);
        else
        {
            printf("成绩应大于%d小于%d请重新输入", XD, XUP);
            getchar();
            getchar();//第一个getchar会读取缓冲区剩下的\n 不起作用
            goto reenter3;
        }
    reenter4:;
        printf("请输入程算成绩：");
        scanf("%d", &st.cs);
        a = searchwjf(st.cs);
        if (a);
        else
        {
            printf("成绩应大于%d小于%d请重新输入", CD, CUP);
            getchar();
            getchar();//第一个getchar会读取缓冲区剩下的\n 不起作用
            goto reenter4;
        }//先暂时把数据储存在st结构体中
        st.sum = st.wjf + st.xd + st.cs;
        s = (node*)malloc(sizeof(node));//开辟一块内存
        *s = st;//将读取的数据赋给开辟的内存上
        s->next = plist->next;
        plist->next = s;
        s = NULL;//抹去s所指以便下次指向新结构体
        printf("添加成功！是否继续输入信息(是--1/否--0):");
        scanf("%d", &goon);
    }



}
int searchrepitition(unsigned long long newid, node* plist)
{

    int repete = 1;//用于检测是否学号有重复的量
    node* p = plist->next;//用于遍历目前所有数据的指针
    for (; p; p = p->next)
    {
        if (p->id == newid)
        {
            repete = 0;
        }

    }
    return repete;//1代表没有重复 0代表有重复  
}

int searchwjf(int newgrade)
{
    int valid = 1;
    if (newgrade > WUP)
        valid = 0;
    else if (newgrade < WD)
        valid = 0;
    else;
    return valid;
}
int searchxd(int newgrade)
{
    int valid = 1;
    if (newgrade > XUP)
        valid = 0;
    else if (newgrade < XD)
        valid = 0;
    else;
    return valid;
}
int searchcs(int newgrade)
{
    int valid = 1;
    if (newgrade > CUP)
        valid = 0;
    else if (newgrade < CD)
        valid = 0;
    else;
    return valid;
}
//删除界面
void printDeleteStuInfo(node* plist)
{
    int sure;
    system("cls");
    unsigned long long id;
    node* p;
    searchall(&list);//先把所有已有信息输出

    printf("请输入要删除的学生学号:");
    scanf("%llu", &id);
    node* st = searchbyId(id, &list);
    p = st;

    if (st == NULL)
    {
        printf("该学生暂不存在！");
        return;
    }

    st = st->next;
    printf("___________________________________________________________\n");
    printf("学号        \t姓名\t性别\t微积分\t线代\t程算\t总分\t\n");
    printf("___________________________________________________________\n");
    printf("%llu\t%s\t%s\t%d\t%d\t%d\t%d\t\n", st->id, st->name, st->sex, st->wjf, st->xd, st->cs, st->sum);
    printf("___________________________________________________________\n");
    printf("确定是否删除该学生所有信息？（是-1 否-2）：");
    scanf("%d", &sure);
    if (sure == 1)
    {
        deleteinf(p);
        savefile(&list);
        printf("删除成功！\n");
    }
    else;

}
//删除功能实现
void deleteinf(node* pr)
{
    node* s = pr->next;
    pr->next = s->next;
    s->next = NULL;
    free(s);
}
bool cmp(node a, node b, int way)
{
    if (way == 1)
        return a.sum > b.sum;
    else if (way == 2)
        return a.wjf > b.wjf;
    else if (way == 3)
        return a.xd > b.xd;
    else if (way == 4)
        return a.cs > b.cs;
    else;
}

void StuScoreSort(node* plist,int way)
{   
    for (node* p = plist->next; p != NULL; p = p->next) {
        for (node* q = p; q != NULL; q = q->next)
        {
            if (!cmp(*p, *q, way))
            {
                //交换数据域
                node t = *p;
                *p = *q;
                *q = t;
                //交换指针域
                t.next = p->next;
                p->next = q->next;
                q->next = t.next;
            }
        }
    }
}
int savefile(node* plist) 
{
    FILE* fpw = fopen("C:\\Users\\weasley\\Desktop\\Project1\\original.txt", "w");
    if (fpw == NULL) return 0;
    node* p = plist->next;
    while (p != NULL) 
    {
        fprintf(fpw, "%llu %s %s %d %d %d %d\n", p->id, p->name, p->sex, p->wjf, p->xd, p->cs, p->sum);
        p = p->next;
    }
    return 1;
}